/* $Id: fpgen.sv,v 1.1.1.1 2014-03-12:15:52:07 kkzhang Exp $ */
/*
 * Authors:	kkzhang@xx.com
 * Create Time:	2014-03-12:15:52:07
 * Description:	
 * 
 */

`include "str_pkg.svh"
`include "float_arith_pkg.svh"

import str_pkg::*;
import float_arith::*;
  

typedef enum logic [1:0] {
			  MADD = 2'b00,
			  MSUB = 2'b01,
			  NMADD =2'b11,
			  NMSUB =2'b10 
			  } insn_e;

	    
// class FpCase #(type T=float32_t);
class FpCase;
   fp_cfg_t fp_cfg;
   // T a, b;
   float32_t a, b, c;
   insn_e insn;

   function FpCase copy();
      FpCase fc = new();
      fc.fp_cfg = fp_cfg;
      fc.a = a;
      fc.b = b;
      fc.c = c;
      fc.insn = insn;
      return fc;
   endfunction // copy
      
   function void display();
      $display("fp_cfg:%b, insn:%s, a=%x, b=%x, c=%x", fp_cfg, insn.name(), a, b, c);
   endfunction // display
   
endclass // FpCase


// ================================================================================
// Notice: not use handle or nested class in BaseFpCase & its derived class, 
//  since 'new' is used to copy its instance when needed which is shallow copy !
// ================================================================================
virtual class BaseFpCase;
   string name;			// test-case name
   // pure virtual function void put(FpCase #(float32_t) fc, int idx=0);	//put the data to the corresponding position
   pure virtual function void put(FpCase dat, int idx=0);	//put the data to the corresponding position
   // pure virtual function int num(); // the cycle, only for randc vars

   virtual function BaseFpCase copy();
      BaseFpCase c = new this;	// copy current object, it's shallow copy
      return c;
   endfunction
   
   virtual function int op_width(); // FIXME: width of operand, used to judge operand fields 
      return 0;
   endfunction // op_width
   
endclass // BaseFpCase


class FpCfgCase extends BaseFpCase;
   local rand fp_cfg_t fp_cfg;	// or randc ??
   local fp_cfg_t mask, const_fields;
     
   constraint c_fp_cfg { (fp_cfg & mask) == const_fields; };

   function new(fp_cfg_t fp_cfg);
      mask = '0;
      const_fields = '0;
      for(int i=0;i<$bits(fp_cfg);i++)
	begin
	   if(fp_cfg[i] !== 1'bx) // 0/1
	     begin
		mask[i] = 1'b1;
		const_fields[i] = fp_cfg[i];
	     end
	end
   endfunction // new

   // virtual function int num();
   //    byte  n = 0;
   //    for(int i=0;i<$bits(mask);i++)
   // 	if(mask[i] == 0) n++;
   //    return 1<<n;
   // endfunction // size

   virtual function void put(FpCase dat, int idx);
      dat.fp_cfg = fp_cfg;
   endfunction // put

   // static function BaseFpCase create(fp_cfg_t fp_cfg);
   //    FpCfgRandc c = new(fp_cfg);
   //    return c;
   // endfunction // create

endclass // FpCfgCase

   
// instruction
class FpInsnCase extends BaseFpCase;
   rand shortint unsigned insn_idx; // or randc ???
   local insn_e insn_array[];

   constraint c_insn {
      insn_idx < insn_array.size();
   };
   
   function new(insn_e ilist[]);
     if(ilist.size() == 0)
       begin
	  $display("insn list is empty");
	  $finish;
       end
     insn_array = ilist;
   endfunction // new

   // virtual function int num();
   //    return insn_array.size();
   // endfunction // size
   
   virtual function void put(FpCase dat, int idx);
      dat.insn = insn_array[insn_idx];
   endfunction // put

   // virtual function BaseFpCase copy();
   //    FpInsnCase c = new(insn_array);
   //    c.insn_idx = insn_idx;
   //    return c;
   // endfunction // copy
   
   // static function BaseFpCase create(input ucode_t ulist[$]);
   //    FpInsnRandc c = new(ulist);
   //    return c;
   // endfunction // create
   
endclass // FpInsnCase



// class BaseFp32Case extends BaseFpCase;
//    protected rand float32_t val;

//    virtual function void put(FpCase dat, input int idx);
//    //    assert(idx < 12);
//    //    if(idx >= 8)
//    // 	dat.op_c.w[3-(idx-8)] = val;
//    //    else if(idx >= 4)
//    // 	dat.op_b.w[3-(idx-4)] = val;
//    //    else
//    // 	dat.op_a.w[3-idx] = val;
//    // endfunction // put

//    virtual function int num();
//       return 0;
//    endfunction // size

//    virtual function int op_width();
//       return 32;
//    endfunction // width
   
// endclass // BaseFp32Case


// class BaseFp64Case extends BaseFpCase;
//    protected rand float64_t val;

//    // virtual function void put(FpCase dat, input int idx);
//    //    assert(idx < 6);
//    //    if(idx >= 4)
//    // 	dat.op_c.d[1-(idx-4)] = val;
//    //    else if(idx >= 2)
//    // 	dat.op_b.d[1-(idx-2)] = val;
//    //    else
//    // 	dat.op_a.d[1-idx] = val;
//    // endfunction // put


//    virtual function int num();
//       return 0;
//    endfunction // size

//    virtual function int op_width();
//       return 64;
//    endfunction // width
   
// endclass // BaseFp64Case


class BaseFp32MonoCase extends BaseFpCase;
   protected rand float32_t a;

   virtual function void put(FpCase dat, int idx);
      if(idx == 0)
	dat.a = a;
      else
	dat.b = a;
   //    assert(idx < 12);
   //    if(idx >= 8)
   // 	dat.op_c.w[3-(idx-8)] = val;
   //    else if(idx >= 4)
   // 	dat.op_b.w[3-(idx-4)] = val;
   //    else
   // 	dat.op_a.w[3-idx] = val;
   endfunction // put

   // virtual function int num();
   //    return 0;
   // endfunction // size

   virtual function int op_width();
      return 32;
   endfunction // width
   
endclass // BaseFp32MonoCase


class BaseFp32DualCase extends BaseFpCase;
   protected rand float32_t a, b;
   
   virtual function void put(FpCase dat, int idx);
      dat.a = a;
      dat.b = b;
   endfunction // put

   virtual function int op_width();
      return 32*2;
   endfunction // width
   
endclass // BaseFp32DualCase


class BaseFp32TriCase extends BaseFpCase;
   protected rand float32_t a, b, c;
   
   virtual function void put(FpCase dat, int idx);
      dat.a = a;
      dat.b = b;
      dat.c = c;
   endfunction // put

   virtual function int op_width();
      return 32*3;
   endfunction // width
endclass // BaseFp32TriCase

   
// ============================== Fp num Case ==============================
// -------------------- f32 to i32 --------------------
// class FC_f32_test extends BaseFp32Case;
   
//    };		

// endclass // FpCase_near_0

class F32_special_mono extends BaseFp32MonoCase;
   randc float32_t sp_val;
   local float32_t f32_special[] = '{
				     '{0, 0, 0}, // +0
				     '{1, 0, 0}, // -0
				     '{0, 0, 1}, // pos min subnormal
				     '{1, 0, 1}, // neg min subnormal
				     '{0, 0, 23'h7f_ffff}, // pos max subnormal
				     '{1, 0, 23'h7f_ffff}, // neg max subnormal
      				     '{0, 1, 0}, // pos min normal
				     '{1, 1, 0}, // neg min normal
				     
				     '{0, 8'hfe, 23'h7f_ffff}, // pos max normal
				     '{1, 8'hfe, 23'h7f_ffff}, // neg max normal

				     '{0, 8'hff, 23'h0}, // +inf
				     '{1, 8'hff, 23'h0}, // -inf
				     '{0, 8'hff, 23'h40_0000}, // +qNaN
				     '{1, 8'hff, 23'h40_0000}, // -qNaN
				     '{0, 8'hff, 1},	     // +sNaN
				     '{1, 8'hff, 1}	     // -sNaN
				     };
   

   constraint c {
      sp_val inside f32_special;
   };

   function void post_randomize();
      if(super) super.post_randomize();
      this.a = sp_val;
   endfunction
   
   virtual function int num();
      return f32_special.size();
   endfunction // size

endclass // F32_special


// for debug ...   --- need improve ... ???
class F32_special_dual extends BaseFp32DualCase;
   // randc float32_t sp_val1, sp_val2;
   rand float32_t sp_val1, sp_val2;
   local float32_t f32_special[] = '{
				     '{0, 0, 0}, // +0
				     '{1, 0, 0}, // -0
				     '{0, 0, 1}, // pos min subnormal
				     '{1, 0, 1}, // neg min subnormal
				     '{0, 0, 23'h7f_ffff}, // pos max subnormal
				     '{1, 0, 23'h7f_ffff}, // neg max subnormal
      				     '{0, 1, 0}, // pos min normal
				     '{1, 1, 0}, // neg min normal
				     
				     '{0, 8'hfe, 23'h7f_ffff}, // pos max normal
				     '{1, 8'hfe, 23'h7f_ffff}, // neg max normal

				     '{0, 8'hff, 23'h0}, // +inf
				     '{1, 8'hff, 23'h0}, // -inf
				     '{0, 8'hff, 23'h40_0000}, // +qNaN
				     '{1, 8'hff, 23'h40_0000}, // -qNaN
				     '{0, 8'hff, 1},	     // +sNaN
				     '{1, 8'hff, 1}	     // -sNaN
				     };
   

   constraint c {
      sp_val1 inside f32_special;
      sp_val2 inside f32_special;
   };

   function void post_randomize();
      if(super) super.post_randomize();
      this.a = sp_val1;
      this.b = sp_val2;
   endfunction
   
   // virtual function int num();
   //    return f32_special.size();
   // endfunction // size

endclass // F32_special

// ------------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------------------------
// ------------------------------------------------------------------------------------------------------------------------


// ======================================================================
// add/sub shift test
// ======================================================================
class F32_add_sub_shift extends BaseFp32DualCase;
   local rand bit [7:0] exp_diff;
	 
   constraint c_sub {
      a.exp < 8'hff;		// normal & subnormal & 0
      b.exp < 8'hff;

      if(a.exp>=b.exp)
     exp_diff == a.exp-b.exp-(a.exp && b.exp==0);
      else
     exp_diff == b.exp-a.exp-(b.exp && a.exp==0);
      
      exp_diff dist { [0:28]:/60, [29:255]:/40};
   }
endclass

  
// a + (-b)
// -a + b
// a - +b

// add
// a b has different sign a+(-b) or (-a) + b => a-b or b-a

// sub
// a b have same sign
// a - (b), (-a) - (-b) => a-b or b - a


// ======================================================================
// add/sub overflow and near overflow test
// ======================================================================
class F32_add_sub_overflow #(bit is_sub=0) extends BaseFp32DualCase;
   local rand bit [7:0] exp_diff;
   local rand bit [22+2:0] frac_sum;
   local rand bit [7:0] exp_big;
	 
   constraint c_sub {
      a.sign ^ b.sign == is_sub; // a,b have the same sign when ADD, diff when SUB => the operation is a + b
      a.exp < 8'hff;		// normal & subnormal & 0
      b.exp < 8'hff;

      if(a.exp >= b.exp)
     {
      exp_diff == a.exp - b.exp - (a.exp && b.exp==0);
      frac_sum == {a.exp > 0, a.sig} + ({b.exp > 0, b.sig} >> exp_diff);
      exp_big == a.exp;
   }
      else	// if(a.exp < b.exp)
     {	
      exp_diff == b.exp - a.exp - (b.exp && a.exp==0);
      // ma == {a.exp > 0, a.sig} >> exp_diff;
      // mb == {b.exp > 0, b.sig};
      frac_sum == {b.exp > 0, b.sig} + ({a.exp > 0, a.sig} >> exp_diff);
      exp_big == b.exp;
   }
      
      // exp_big == ((a.exp >= b.exp) ? a.exp : b.exp);
      (exp_big + frac_sum[24]) dist { [8'hfc:8'hfe]:/50, // near overflow (or overflow when in spec rounding mode)
      				      8'hff:/50 };	 // overflow
   };
endclass // F32_add_sub_cancellation

class F32_add_overflow extends F32_add_sub_overflow #(.is_sub(0)); endclass
class F32_sub_overflow extends F32_add_sub_overflow #(.is_sub(1)); endclass





class F32_add_sub_lzd #(bit is_sub=0) extends BaseFp32DualCase;
   local rand bit [7:0] exp_diff;
   local rand bit [23:0] frac_diff;;
   local rand bit [7:0] exp_big;
	 
   constraint c_sub {
      a.sign ~^ b.sign == is_sub;
      a.exp < 8'hff;		// normal & subnormal & 0
      b.exp < 8'hff;

      if(a.exp > b.exp)
     {
      exp_diff == a.exp - b.exp - (a.exp && b.exp==0);
      frac_diff == {a.exp > 0, a.sig} - ({b.exp > 0, b.sig} >> exp_diff);
      exp_big == a.exp;
   }
      else if(a.exp < b.exp)
     {	
      exp_diff == b.exp - a.exp - (b.exp && a.exp==0);
      frac_diff == {b.exp > 0, b.sig} - ({a.exp > 0, a.sig} >> exp_diff);
      exp_big == b.exp;
   }
      else			// a.exp == b.exp
     {
      exp_diff == 0;
      
      if(a.sig >= b.sig)
     frac_diff == a.sig - b.sig;
      else
     frac_diff == b.sig - a.sig;

      // a.sig >= b.sig;
      // frac_diff == a.sig - b.sig;

      exp_big == a.exp;
   }


      // how to descript lzd ??
      frac_diff[23:20] == 4'b0000;
   };
   
endclass // F32_add_sub_lzd

class F32_add_lzd extends F32_add_sub_lzd #(.is_sub(0)); endclass
class F32_sub_lzd extends F32_add_sub_lzd #(.is_sub(1)); endclass


class F32_add_sub_rnd #(bit is_sub=0) extends BaseFp32DualCase;
   local rand bit [7:0] exp_diff;
   local rand bit [23:0] frac_diff;;
   local rand bit [7:0] exp_big;
	 
   constraint c_sub {
      a.sign ^ b.sign == is_sub;
      a.exp < 8'hff;		// normal & subnormal & 0
      b.exp < 8'hff;

      if(a.exp > b.exp)
     {
      exp_diff == a.exp - b.exp - (a.exp && b.exp==0);
      frac_diff == {a.exp > 0, a.sig} - ({b.exp > 0, b.sig} >> exp_diff);
      exp_big == a.exp;
   }
      else if(a.exp < b.exp)
     {	
      exp_diff == b.exp - a.exp - (b.exp && a.exp==0);
      frac_diff == {b.exp > 0, b.sig} - ({a.exp > 0, a.sig} >> exp_diff);
      exp_big == b.exp;
   }
      else			// a.exp == b.exp
     {
      exp_diff == 0;
      
     //  if(a.sig >= b.sig)
     // frac_diff == a.sig - b.sig;
     //  else
     // frac_diff == b.sig - a.sig;
      a.sig >= b.sig;
      frac_diff == a.sig - b.sig;

      exp_big == a.exp;
   }


      // how to descript rnd (path) ??
		     
   };
   
endclass // F32_add_sub_lzd

class F32_add_rnd extends F32_add_sub_rnd #(.is_sub(0)); endclass
class F32_sub_rnd extends F32_add_sub_rnd #(.is_sub(1)); endclass


// ======================================================================
// add/sub cancellation test
// ======================================================================
class F32_add_sub_cancellation #(bit is_sub=0) extends BaseFp32DualCase;
   // rand bit [22+1:0] ma, mb;
   local rand bit [7:0] exp_diff;
   local rand bit [22+1:0] frac_diff;
	 
   constraint c_sub {
		     a.sign ^ b.sign == ~is_sub; // a,b have the same sign when SUB, diff when ADD
		     a.exp < 8'hff;		// normal & subnormal & 0
		     b.exp < 8'hff;

		     if(a.exp > b.exp)
		     {
      exp_diff == a.exp - b.exp - (a.exp && b.exp==0);
      frac_diff == {a.exp > 0, a.sig} - ({b.exp > 0, b.sig} >> exp_diff); // must > 0
   }
		     else if(a.exp < b.exp)
		     {
      exp_diff == b.exp - a.exp - (b.exp && a.exp==0);
      // ma == {a.exp > 0, a.sig} >> exp_diff;
      // mb == {b.exp > 0, b.sig};
      frac_diff == {b.exp > 0, b.sig} - ({a.exp > 0, a.sig} >> exp_diff);
   }
		     else	// a.exp == b.exp
     {
      frac_diff == {1'b0, (a.sig >= b.sig) ? (a.sig-b.sig) : (b.sig - a.sig)};
   }

      frac_diff < 24'h00_ffff;	// the result need shift left

   };
endclass // F32_add_sub_cancellation

class F32_add_cancellation extends F32_add_sub_cancellation #(.is_sub(0));
endclass // F32_add_cancellation

class F32_sub_cancellation extends F32_add_sub_cancellation #(.is_sub(1));
endclass // F32_sub_cancellation




// ======================================================================
// random float32
// ======================================================================
class F32_rand extends BaseFp32DualCase;

   constraint c_rand {
      // a.exp < 8'hff;		// normal & subnormal & 0
      // b.exp < 8'hff;
   }
   
endclass




class F32_test extends BaseFp32TriCase;

   constraint c_rand {
      // a.exp + b.exp <= 254;
      // a.exp + b.exp <= 300;
      // a.exp > 140;
      // b.exp > 140;
      // a.exp == 0;
      // b.exp == 0;
      // a.exp + b.exp -127 >= 1;
      // a.exp >= 1;
      // b.exp >= 1;
      
      // a.exp <= 254; b.exp <= 254; c.exp <= 254;

      // a.sign == 0; a.exp == 255; a.sig == '0; // +inf
      // b.sign == 0; b.exp <= 254;	      // +num
      // c.sign == 1; c.exp == 255; c.sig == '0; // -inf

      // (a.exp == 255 || b.exp == 255 || c.exp == 255) == 1;
		      
      
      // a.exp == 0;
      // b.exp == 0;
      // a.exp <= 254; b == '0;
      // a == 0; b == 0;


      // ==================== test exact 0 ====================
      // a.exp == 100;
      // b.exp == 140;
      // c.exp == 114;

      // a.sig == 23'h7ab_000;
      // b.sig == 23'h6c2_000;
      // c.sig == 23'h673_996;

      // a.sign ^ b.sign == 0;
      // c.sign == 1;

      
      // ==================== test diff lzn ====================
      // a.exp == 52;
      // b.exp == 52;
      // a.sig == 23'b111_1111_1111_1111_1111_1110;
      // b.sig == 23'b000_0000_0000_0000_0000_0001;

      // c.exp == 0;
      // c.sig == 23'b000_0000_0000_0000_0000_0001;

      // a.sign == b.sign; c.sign == 1;
      

      
      
      // c.exp - a.exp - b.exp +126 >= 0;
      // {1'b0, c.exp} + 9'd126 >= {1'b0, a.exp} + {1'b0, b.exp};
      // {1'b0, c.exp} + 9'd126 < {1'b0, a.exp} + {1'b0, b.exp};
      // c.exp - a.exp - b.exp + 126 < 0;
      // c.exp + 126 < a.exp + b.exp;
      
      // a.sign == 0;
      // b.sign == 0;
      // c.sign == 0;
      // c.sign == 1;
   }
   
endclass

// // cancellation and subnormal result	-- it works not very well !!
// class FC_f32_add_sub_cancellation_subnormal#(parameter bit is_sub=1) extends BaseFp32DualCase;
//    // rand bit [22+1:0] ma, mb;
//    local rand bit [7:0] exp_diff;
//    local rand bit [22+1:0] frac_diff;
//    rand bit [22:0] mask;	// 23 bits
   
//    constraint c_sub {
// 		     a.sign == b.sign ^ ~is_sub; // a,b have the same sign when SUB, otherwise the diff sign
// 		     a.exp < 8'hff;		// normal & subnormal & 0
// 		     b.exp < 8'hff;

// 		     if(a.exp > b.exp)
// 		     {
//       exp_diff == a.exp - b.exp - (a.exp && b.exp==0);
//       frac_diff == {a.exp > 0, a.sig} - ({b.exp > 0, b.sig} >> exp_diff); // must > 0
//    }
// 		     else if(a.exp < b.exp)
// 		     {
//       exp_diff == b.exp - a.exp - (b.exp && a.exp==0);
//       // ma == {a.exp > 0, a.sig} >> exp_diff;
//       // mb == {b.exp > 0, b.sig};
//       frac_diff == {b.exp > 0, b.sig} - ({a.exp > 0, a.sig} >> exp_diff);
//       }
// 		     else	// a.exp == b.exp
// 		     {
//       frac_diff == {1'b0, (a.sig >= b.sig) ? (a.sig-b.sig) : (b.sig - a.sig)};
//    }

//       frac_diff <= 24'h7f_ffff;	// the result need shift left
//       frac_diff[22:0] > 0;
      
//       a.exp <= 23;
//       b.exp <= 23;
	
//       mask == (({22'b0, 1'b1}<<a.exp)-1); // max is
//       (frac_diff[23:1] & mask) == 0;	 // subnormal
		     
//    };
// endclass



typedef BaseFpCase case_pattern_t[$];

class GenOpCase #(type T = BaseFp32MonoCase);
   static function BaseFpCase create(string casename);
      T c = new();		// c is an automatic var
      c.name = casename;
      return c;
   endfunction // create
endclass // GenOpCase

     

class FpGen;
   local FpCase case_data;
   local mailbox gen2drvr;

   // vars for print the progress
   local int 	 update_percent_cnt;
   local int 	 update_percent_delta;
   local int 	 run_cnt;

   
   function new(mailbox gen2drvr);
      if(gen2drvr == null)
	begin
	   $display("**ERROR** : gen2drvr is null");
	   $finish;
	end
      
      this.gen2drvr = gen2drvr;
   endfunction // new


   // ========================================
   // func and macro for add vary case 
   // ======================================== 
   function BaseFpCase FP_CFG(fp_cfg_t fp_cfg);
      FpCfgCase cfg_case = new(fp_cfg);
      return cfg_case;
   endfunction // FPCFG
   
   function BaseFpCase INSN_LIST(insn_e ilist[]);
      FpInsnCase insn_case = new(ilist);
      return insn_case;
   endfunction // INSN_LIST

`define OP_CASE(cs) GenOpCase #(cs)::create(`"cs`")

   
   task run_case_pattern(case_pattern_t cp, int num);
      case_pattern_t case_pattern;
      FpCase fc = new();

      // init vars for print progress
      update_percent_delta = num / 1000; // 0.1%
      update_percent_cnt = update_percent_delta;
      run_cnt = 0;

      $display("### total %d cases", num);

      
      foreach(cp[i])
	case_pattern.push_back(cp[i].copy());
      
      repeat(num) begin
	 // gen a case pattern
         foreach(case_pattern[i]) begin
	    assert(case_pattern[i].randomize());
	    case_pattern[i].put(fc, 0);
	 end
	 

	 // print current progress
	 update_percent_cnt--;
	 if(!update_percent_cnt) begin
	       update_percent_cnt = update_percent_delta;
	       run_cnt += update_percent_delta;
	    // $write("finish %0.1f%%\15", real'(run_cnt)/num*100.0);
	    $write("\15finish %0.1f%%", real'(run_cnt)/num*100.0);
	       $fflush(1);
	    end
	 
	 // send case
	 gen2drvr.put(fc.copy());
	 // fc.display();
      end // repeat (num)
      $display();
   endtask // run_case_pattern
   
      

   task start();

      case_pattern_t cp[$];


      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		       INSN_LIST({SUB}),
      // 		       `OP_CASE(F32_sub_lzd)
      // 		      } );




      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		       INSN_LIST({ADD}),
      // 		       `OP_CASE(F32_add_rnd)
      // 		      } );



      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		       INSN_LIST({ADD}),
      // 		       `OP_CASE(F32_add_overflow)
      // 		      } );


      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		       INSN_LIST({SUB}),
      // 		       `OP_CASE(F32_test)
      // 		      } );


      

      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		       INSN_LIST({ADD}),
      // 		       `OP_CASE(F32_special_dual)
      // 		      } );
      
      
      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		      INSN_LIST({ADD}),
      // 		       // `OP_CASE(F32_add_sub_shift), `OP_CASE(F32_add_overflow), `OP_CASE(F32_add_cancellation), `OP_CASE(F32_rand)
      // 		       `OP_CASE(F32_add_sub_shift)
      // 		      } );

      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		      INSN_LIST({ADD}),
      // 		       `OP_CASE(F32_add_overflow)
      // 		      } );

      // cp.push_back( '{ FP_CFG('{default:'x}),
      // 		      INSN_LIST({ADD}),
      // 		       `OP_CASE(F32_add_cancellation)
      // 		      } );
      

      // FP_CFG('{rounding_mode:RU, default:'x}),
      
      cp.push_back( '{ FP_CFG('{default:'x}),
      		       // INSN_LIST({MADD, MSUB, NMADD, NMSUB}),
		       // INSN_LIST({MADD, NMADD}),
		       INSN_LIST({MADD}),
		       // INSN_LIST({MSUB}),
		       // INSN_LIST({NMSUB}),
      		       `OP_CASE(F32_test)
      		      } );



      
      // cp[0] = { FP_CFG('{default:'x}),
      // 		INSN_LIST({ADD}),
      // 		`OP_CASE(F32_add_cancellation)
      // 		};

      // cp[1] = { FP_CFG('{default:'x}),
      // 		INSN_LIST({ADD, SUB}),
      // 		`OP_CASE(F32_rand)
      // 		};
      
      // `OP_CASE(F32_add_cancellation)
      // `OP_CASE(F32_sub_overflow)
			    
      // `OP_CASE(F32_add_sub_cancellation_subnormal)
      // `OP_CASE(FC_f32_add_sub_shift)
      // };
      // case_pattern_t cp2 = { FP_CFG('{default:'x}),
      // 			     INSN_LIST({SUB}),
      // 			     `OP_CASE(FC_f32_addsub_rand)
      // 			    };


      foreach(cp[i])
	begin
	   $display("run op-case :  %s", cp[i][$].name);
	   // run_case_pattern(cp[i], 32'd10_0000);
	   run_case_pattern(cp[i], 32'd100_0000);
	end
	// $display("i = %d", i);
      // run_case_pattern(cp2, 32'd10_0000);
   
   endtask // start
   
	 

   
endclass // FpGen
